< Back to home

Analizando el dataset bataxi en clase

In [0]:
import pandas as pd
df = pd.read_csv('https://query.data.world/s/guh6xsutvf7cz5iajnygsf6c64nf6s')
In [0]:
df
Out[0]:
id_viaje_r id_taxista_r fecha_inicio fecha_fin duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros
0 1 499 2017-05-01 00:12:48.000 2017-05-01 00:31:09.000 1101 -58.387303 -34.594316 -58.431452 -34.578193 3
1 2 715 2017-05-01 00:17:21.000 2017-05-01 00:28:36.000 675 -58.413992 -34.582760 -58.438494 -34.587420 1
2 3 429 2017-05-01 00:16:03.000 2017-05-01 00:36:33.000 1230 -58.429912 -34.599420 -58.483171 -34.564596 1
3 4 164 2017-05-01 00:34:39.000 2017-05-01 00:54:57.000 1218 -58.447841 -34.633739 -58.439394 -34.593648 2
4 5 499 2017-05-01 00:32:02.000 2017-05-01 00:48:37.000 995 -58.433165 -34.579621 -58.403720 -34.599863 2
... ... ... ... ... ... ... ... ... ... ...
19143 19144 506 2017-08-31 23:45:00.000 2017-08-31 23:57:23.000 743 -58.438994 -34.614444 -58.443941 -34.585864 1
19144 19145 256 2017-08-31 23:53:00.000 2017-09-01 00:01:09.000 489 -58.458194 -34.622391 -58.436735 -34.618064 2
19145 19146 423 2017-08-31 23:53:00.000 2017-09-01 00:08:49.000 949 -58.409810 -34.595529 -58.384760 -34.609911 1
19146 19147 1114 2017-08-31 23:58:00.000 2017-09-01 00:08:36.000 636 -58.453700 -34.617587 -58.439362 -34.624317 2
19147 19148 781 2017-08-31 23:58:00.000 2017-09-01 00:25:26.000 1646 -58.393538 -34.601992 -58.471986 -34.565733 1

19148 rows × 10 columns

In [0]:
df.describe()
Out[0]:
id_viaje_r id_taxista_r duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros
count 19148.000000 19148.00000 19148.000000 19148.000000 19148.000000 19148.000000 19148.000000 19148.000000
mean 9574.500000 555.22065 923.268801 -58.432996 -34.600981 -58.430427 -34.599348 1.468508
std 5527.695813 328.83645 441.574700 0.035446 0.024021 0.039256 0.028003 0.734087
min 1.000000 1.00000 0.000000 -58.530481 -34.697275 -58.873765 -34.815577 1.000000
25% 4787.750000 279.00000 573.750000 -58.458370 -34.619576 -58.456854 -34.618200 1.000000
50% 9574.500000 545.00000 860.000000 -58.432488 -34.601917 -58.427332 -34.599675 1.000000
75% 14361.250000 833.00000 1219.000000 -58.406035 -34.584902 -58.401037 -34.582150 2.000000
max 19148.000000 1215.00000 3740.000000 -58.342968 -34.536543 -58.271448 -34.420709 4.000000
In [0]:
#imprimiendo la primer parte del dataset
df.head()
Out[0]:
id_viaje_r id_taxista_r fecha_inicio fecha_fin duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros
0 1 499 2017-05-01 00:12:48.000 2017-05-01 00:31:09.000 1101 -58.387303 -34.594316 -58.431452 -34.578193 3
1 2 715 2017-05-01 00:17:21.000 2017-05-01 00:28:36.000 675 -58.413992 -34.582760 -58.438494 -34.587420 1
2 3 429 2017-05-01 00:16:03.000 2017-05-01 00:36:33.000 1230 -58.429912 -34.599420 -58.483171 -34.564596 1
3 4 164 2017-05-01 00:34:39.000 2017-05-01 00:54:57.000 1218 -58.447841 -34.633739 -58.439394 -34.593648 2
4 5 499 2017-05-01 00:32:02.000 2017-05-01 00:48:37.000 995 -58.433165 -34.579621 -58.403720 -34.599863 2
In [0]:
#imprimiendo la ultima parte del dataset
df.tail()
Out[0]:
id_viaje_r id_taxista_r fecha_inicio fecha_fin duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros
19143 19144 506 2017-08-31 23:45:00.000 2017-08-31 23:57:23.000 743 -58.438994 -34.614444 -58.443941 -34.585864 1
19144 19145 256 2017-08-31 23:53:00.000 2017-09-01 00:01:09.000 489 -58.458194 -34.622391 -58.436735 -34.618064 2
19145 19146 423 2017-08-31 23:53:00.000 2017-09-01 00:08:49.000 949 -58.409810 -34.595529 -58.384760 -34.609911 1
19146 19147 1114 2017-08-31 23:58:00.000 2017-09-01 00:08:36.000 636 -58.453700 -34.617587 -58.439362 -34.624317 2
19147 19148 781 2017-08-31 23:58:00.000 2017-09-01 00:25:26.000 1646 -58.393538 -34.601992 -58.471986 -34.565733 1
In [0]:
#maximo id de un taxista en la app --> posible cantidad de taxistas, aunque puede que hayan agujeros en el medio
df['id_taxista_r'].max()
Out[0]:
1215
In [0]:
#minimo id de un taxista en la app
df['id_taxista_r'].min()
Out[0]:
1
In [0]:
#hago el count de id únicos --> al final me da igual que el maximo, son 1215 taxistas
df['id_taxista_r'].nunique()
Out[0]:
1215
In [0]:
print('Tengo', df['id_taxista_r'].nunique(), 'taxistas que están usando la app en este período')
Tengo 1215 taxistas que están usando la app en este período
In [0]:
from IPython.display import HTML # --> importo HTML para poder usar bold
HTML("Hay <b>" + str(df['id_taxista_r'].nunique()) + "</b> taxistas que usan la app BATaxi en este período")
Out[0]:
Hay 1215 taxistas que usan la app BATaxi en este período
In [0]:
#busco el período que se está teniendo en cuenta en el dataset
#agarro el mínimo de las fechas de inicio y el máximo de las fechas de fin
#tomo los caracteres del 0 al 10 para que me muestre solo la fecha y no la hora
[df['fecha_inicio'].min()[0:10], df['fecha_fin'].max()[0:10]]
Out[0]:
['2017-05-01', '2017-09-01']
In [0]:
#veo el tipo de dato de cada atributo
df.dtypes
Out[0]:
id_viaje_r              int64
id_taxista_r            int64
fecha_inicio           object
fecha_fin              object
duracion                int64
origen_viaje_x        float64
origen_viaje_y        float64
destino_viaje_x       float64
destino_viaje_y       float64
cantidad_pasajeros      int64
dtype: object
In [0]:
#reduzco el tamaño de "cantidad de pasajeros" a un int8 para que ocupe menos memoria
import numpy as np
df = df.astype({"cantidad_pasajeros": np.int8})
In [0]:
#veo el uso de memoria, cantidad de pasajeros ocupa menos que antes (19148 vs 153184)
df.memory_usage()
Out[0]:
Index                    128
id_viaje_r            153184
id_taxista_r          153184
fecha_inicio          153184
fecha_fin             153184
duracion              153184
origen_viaje_x        153184
origen_viaje_y        153184
destino_viaje_x       153184
destino_viaje_y       153184
cantidad_pasajeros     19148
dtype: int64
In [0]:
#agrego una columna con el mes del viaje segun la fecha de inicio
df["mes"] = pd.DatetimeIndex(df['fecha_inicio']).month
df.head()
Out[0]:
id_viaje_r id_taxista_r fecha_inicio fecha_fin duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros mes
0 1 499 2017-05-01 00:12:48.000 2017-05-01 00:31:09.000 1101 -58.387303 -34.594316 -58.431452 -34.578193 3 5
1 2 715 2017-05-01 00:17:21.000 2017-05-01 00:28:36.000 675 -58.413992 -34.582760 -58.438494 -34.587420 1 5
2 3 429 2017-05-01 00:16:03.000 2017-05-01 00:36:33.000 1230 -58.429912 -34.599420 -58.483171 -34.564596 1 5
3 4 164 2017-05-01 00:34:39.000 2017-05-01 00:54:57.000 1218 -58.447841 -34.633739 -58.439394 -34.593648 2 5
4 5 499 2017-05-01 00:32:02.000 2017-05-01 00:48:37.000 995 -58.433165 -34.579621 -58.403720 -34.599863 2 5
In [0]:
#si quiero borrar una columna de la tabla (habia agregado la columna month pero los nombres estan en español) uso "del df['month']"
In [0]:
#agrupo por mes y cuento la cantidad de viajes por mes (como Series)
#https://stackoverflow.com/questions/19384532/get-statistics-for-each-group-such-as-count-mean-etc-using-pandas-groupby (segunda respuesta)
df.groupby(['mes']).size()
Out[0]:
mes
5    3780
6    4368
7    5461
8    5539
dtype: int64
In [0]:
#lo mismo pero como DataFrame
df.groupby(['mes']).size().reset_index(name='count')
Out[0]:
mes count
0 5 3780
1 6 4368
2 7 5461
3 8 5539
In [0]:
#si hago esto es raro porque para todas las columnas me da la el count de viajes (registros)
df.groupby('mes').count()
Out[0]:
id_viaje_r id_taxista_r fecha_inicio fecha_fin duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros
mes
5 3780 3780 3780 3780 3780 3780 3780 3780 3780 3780
6 4368 4368 4368 4368 4368 4368 4368 4368 4368 4368
7 5461 5461 5461 5461 5461 5461 5461 5461 5461 5461
8 5539 5539 5539 5539 5539 5539 5539 5539 5539 5539
In [0]:
#defino cant para no usar los atributos del dataset como si hiciera df[['month', 'id_viaje_r']].groupby('month').count()
df['cant'] = 1
df[['mes', 'cant']].groupby('mes').count()
Out[0]:
cant
mes
5 3780
6 4368
7 5461
8 5539
In [0]:
#importo altair para hacer gráficos
import altair as alt
In [0]:
#guardo la consulta en source1
source1 = df.groupby(['mes']).size().reset_index(name='count')
In [0]:
#hago un gráfico con source1
alt.Chart(source1).mark_bar().encode(
    x='mes',
    y='count'
).properties(width=200).mark_bar(size=25)
Out[0]:
In [0]:
#guardo la consulta en source
source = df[['mes', 'cant']].groupby('mes').count().reset_index()
In [0]:
#hago un gráfico con el código del profe
alt.Chart(source).mark_bar().encode(
    x='mes:O', #le pido que mes sea ordinal para que no me lo muestre con coma
    y='cant'
).properties(width=200).mark_bar(size=25) #properties es para el ancho del gráfico, mark_bar para el ancho de las columnas
Out[0]:
In [0]:
#transpongo el gráfico y le agrego labels a las barras
bars = alt.Chart(source).mark_bar().encode(
    x='cant',
    y='mes:O' #cambio las variables de lugar para transponer
).properties(
    width=450,
    height=150
).mark_bar(size=25)

text = bars.mark_text(
    align='left',
    baseline='middle',
    dx=3  #mueve el texto un poco a la derecha para que no se superponga con la barra
).encode(
    text='cant'
)

(bars + text) #muestro el gráfico
Out[0]:
In [0]:
#instalo para calcular distancias
!pip install geopy
Requirement already satisfied: geopy in /usr/local/lib/python3.6/dist-packages (1.17.0)
Requirement already satisfied: geographiclib<2,>=1.49 in /usr/local/lib/python3.6/dist-packages (from geopy) (1.50)
In [0]:
#calculo la distancia de los viajes segun las coordenadas de origen y destino y la agrego a la columna distancia
from geopy.point import Point
from geopy.distance import geodesic

df['distancia'] = df.apply(lambda dato: int(geodesic( 
    Point(latitude=dato['origen_viaje_y'], longitude=dato['origen_viaje_x']) , 
    Point(latitude=dato['destino_viaje_y'], longitude=dato['destino_viaje_x'])).meters), 
    axis=1)
df.head()
Out[0]:
id_viaje_r id_taxista_r fecha_inicio fecha_fin duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros mes cant distancia
0 1 499 2017-05-01 00:12:48.000 2017-05-01 00:31:09.000 1101 -58.387303 -34.594316 -58.431452 -34.578193 3 5 1 4427
1 2 715 2017-05-01 00:17:21.000 2017-05-01 00:28:36.000 675 -58.413992 -34.582760 -58.438494 -34.587420 1 5 1 2306
2 3 429 2017-05-01 00:16:03.000 2017-05-01 00:36:33.000 1230 -58.429912 -34.599420 -58.483171 -34.564596 1 5 1 6229
3 4 164 2017-05-01 00:34:39.000 2017-05-01 00:54:57.000 1218 -58.447841 -34.633739 -58.439394 -34.593648 2 5 1 4514
4 5 499 2017-05-01 00:32:02.000 2017-05-01 00:48:37.000 995 -58.433165 -34.579621 -58.403720 -34.599863 2 5 1 3512
In [0]:
#importo una función para calcular la distancia entre dos coordenadas de otra forma
import math

def distance(origin, destination):
    lat1, lon1 = origin
    lat2, lon2 = destination
    radius = 6371 # km

    dlat = math.radians(lat2-lat1)
    dlon = math.radians(lon2-lon1)
    a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \
        * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
    d = radius * c

    return d
In [0]:
#agrego una columna distancia2 calculando distancias con la nueva fórmula (va a dar apenas distinto)
df['distancia2'] = df.apply(lambda d: int(1000*distance( 
    (d['origen_viaje_y'], d['origen_viaje_x']) , 
    (d['destino_viaje_y'], d['destino_viaje_x']))), 
    axis=1)
df.head()
Out[0]:
id_viaje_r id_taxista_r fecha_inicio fecha_fin duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros mes cant distancia distancia2
0 1 499 2017-05-01 00:12:48.000 2017-05-01 00:31:09.000 1101 -58.387303 -34.594316 -58.431452 -34.578193 3 5 1 4427 4421
1 2 715 2017-05-01 00:17:21.000 2017-05-01 00:28:36.000 675 -58.413992 -34.582760 -58.438494 -34.587420 1 5 1 2306 2302
2 3 429 2017-05-01 00:16:03.000 2017-05-01 00:36:33.000 1230 -58.429912 -34.599420 -58.483171 -34.564596 1 5 1 6229 6226
3 4 164 2017-05-01 00:34:39.000 2017-05-01 00:54:57.000 1218 -58.447841 -34.633739 -58.439394 -34.593648 2 5 1 4514 4524
4 5 499 2017-05-01 00:32:02.000 2017-05-01 00:48:37.000 995 -58.433165 -34.579621 -58.403720 -34.599863 2 5 1 3512 3511
In [0]:
#histogramas de la duracion y la distancia, con pandas
hist = df[['distancia', 'duracion']].hist()
In [0]:
#histograma de la distancia, con altair

#le pido que lea todas las rows por más que sean más de 5000
alt.data_transformers.disable_max_rows()

alt.Chart(df).mark_bar().encode(
    alt.X("distancia:Q", bin=True),
    y='count()',
)
Out[0]:
In [0]:
#histograma de la duracion, con altair
alt.Chart(df).mark_bar().encode(
    alt.X("duracion:Q", bin=True),
    y='count()',
)
Out[0]:
In [0]:
#calculo la hora de inicio de los viajes para ver horas de mayor demanda, y lo agrego la columna hour
df["hour"] = pd.DatetimeIndex(df['fecha_inicio']).hour
In [0]:
df.head()
Out[0]:
id_viaje_r id_taxista_r fecha_inicio fecha_fin duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros mes cant distancia distancia2 hour
0 1 499 2017-05-01 00:12:48.000 2017-05-01 00:31:09.000 1101 -58.387303 -34.594316 -58.431452 -34.578193 3 5 1 4427 4421 0
1 2 715 2017-05-01 00:17:21.000 2017-05-01 00:28:36.000 675 -58.413992 -34.582760 -58.438494 -34.587420 1 5 1 2306 2302 0
2 3 429 2017-05-01 00:16:03.000 2017-05-01 00:36:33.000 1230 -58.429912 -34.599420 -58.483171 -34.564596 1 5 1 6229 6226 0
3 4 164 2017-05-01 00:34:39.000 2017-05-01 00:54:57.000 1218 -58.447841 -34.633739 -58.439394 -34.593648 2 5 1 4514 4524 0
4 5 499 2017-05-01 00:32:02.000 2017-05-01 00:48:37.000 995 -58.433165 -34.579621 -58.403720 -34.599863 2 5 1 3512 3511 0
In [0]:
df.tail()
Out[0]:
id_viaje_r id_taxista_r fecha_inicio fecha_fin duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros mes cant distancia distancia2 hour
19143 19144 506 2017-08-31 23:45:00.000 2017-08-31 23:57:23.000 743 -58.438994 -34.614444 -58.443941 -34.585864 1 8 1 3202 3210 23
19144 19145 256 2017-08-31 23:53:00.000 2017-09-01 00:01:09.000 489 -58.458194 -34.622391 -58.436735 -34.618064 2 8 1 2025 2021 23
19145 19146 423 2017-08-31 23:53:00.000 2017-09-01 00:08:49.000 949 -58.409810 -34.595529 -58.384760 -34.609911 1 8 1 2797 2795 23
19146 19147 1114 2017-08-31 23:58:00.000 2017-09-01 00:08:36.000 636 -58.453700 -34.617587 -58.439362 -34.624317 2 8 1 1512 1510 23
19147 19148 781 2017-08-31 23:58:00.000 2017-09-01 00:25:26.000 1646 -58.393538 -34.601992 -58.471986 -34.565733 1 8 1 8245 8235 23
In [0]:
#hago un gráfico del count de viajes en cada hora para ver las horas de mayor demanda
alt.Chart(df).mark_line().encode(
    x='hour',
    y='count()'
)
Out[0]:
In [0]:
hist1 = alt.Chart( df ).mark_bar().encode(
    alt.X("distancia:Q", bin=True),
    y='count()',
)
hist2 = alt.Chart( df ).mark_bar().encode(
    alt.X("duracion:Q", bin=True),
    y='count()',
)
# alt.hconcat(hist1, hist2)
# o
hist1 | hist2
Out[0]:

Analizando el dataset de bataxi por mi cuenta

In [0]:
import pandas as pd
df = pd.read_csv('https://query.data.world/s/guh6xsutvf7cz5iajnygsf6c64nf6s')
In [0]:
import altair as alt
In [0]:
df.head()
Out[0]:
id_viaje_r id_taxista_r fecha_inicio fecha_fin duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y cantidad_pasajeros
0 1 499 2017-05-01 00:12:48.000 2017-05-01 00:31:09.000 1101 -58.387303 -34.594316 -58.431452 -34.578193 3
1 2 715 2017-05-01 00:17:21.000 2017-05-01 00:28:36.000 675 -58.413992 -34.582760 -58.438494 -34.587420 1
2 3 429 2017-05-01 00:16:03.000 2017-05-01 00:36:33.000 1230 -58.429912 -34.599420 -58.483171 -34.564596 1
3 4 164 2017-05-01 00:34:39.000 2017-05-01 00:54:57.000 1218 -58.447841 -34.633739 -58.439394 -34.593648 2
4 5 499 2017-05-01 00:32:02.000 2017-05-01 00:48:37.000 995 -58.433165 -34.579621 -58.403720 -34.599863 2

Veamos cómo evoluciona la cantidad de taxistas registrados mes a mes.

Primero agrego el atributo 'mes' al dataset.

In [0]:
df['mes'] = pd.DatetimeIndex(df['fecha_inicio']).month
df[['fecha_inicio','mes']]
Out[0]:
fecha_inicio mes
0 2017-05-01 00:12:48.000 5
1 2017-05-01 00:17:21.000 5
2 2017-05-01 00:16:03.000 5
3 2017-05-01 00:34:39.000 5
4 2017-05-01 00:32:02.000 5
... ... ...
19143 2017-08-31 23:45:00.000 8
19144 2017-08-31 23:53:00.000 8
19145 2017-08-31 23:53:00.000 8
19146 2017-08-31 23:58:00.000 8
19147 2017-08-31 23:58:00.000 8

19148 rows × 2 columns

Ahora calculo cuántos ids de taxistas distintos hay en cada mes.

In [0]:
source = df.groupby(['mes']).id_taxista_r.nunique().reset_index(name='count')
source
Out[0]:
mes count
0 5 689
1 6 698
2 7 726
3 8 806

Vemos que la cantidad de taxistas registrados va aumentando mes a mes, lo cual sugiere que la app aumentó su popularidad.

Muestro el aumento en gráficos. Primero usando Altair.

In [0]:
alt.Chart(source).mark_bar().encode(
    x=alt.X('mes:O', title='Mes', axis=alt.Axis(labelAngle=0)),
    y=alt.Y('count', title='Cantidad de taxistas registrados')
).properties(width=300).mark_bar(size=30)
Out[0]:

Ahora usando Pandas.

In [0]:
chart = source.plot.bar(x='mes',y='count',rot=0, legend=False)
chart.set_xlabel('Mes')
chart.set_ylabel('Número de taxistas registrados')
chart.set_xticklabels(chart.get_xticklabels(), rotation=0);

Ahora analicemos los días de la semana con más viajes.

Primero agrego una columna con el día de la semana correspondiente a cada viaje.

In [0]:
df['dia_de_la_semana'] = pd.DatetimeIndex(df['fecha_inicio']).dayofweek
df[['fecha_inicio','dia_de_la_semana']].head(200)
Out[0]:
fecha_inicio dia_de_la_semana
0 2017-05-01 00:12:48.000 0
1 2017-05-01 00:17:21.000 0
2 2017-05-01 00:16:03.000 0
3 2017-05-01 00:34:39.000 0
4 2017-05-01 00:32:02.000 0
... ... ...
195 2017-05-04 00:41:55.000 3
196 2017-05-04 00:43:16.000 3
197 2017-05-04 01:01:18.000 3
198 2017-05-04 02:44:37.000 3
199 2017-05-04 03:19:21.000 3

200 rows × 2 columns

Luego agrupo por día de la semana y hago un count para contar los viajes de cada día.

In [0]:
source2 = df.groupby(['dia_de_la_semana']).id_viaje_r.nunique().reset_index(name='count')
source2['dia_de_la_semana_nombre'] = ['Lunes','Martes','Miércoles','Jueves','Viernes','Sábado','Domingo']
source2
Out[0]:
dia_de_la_semana count dia_de_la_semana_nombre
0 0 2280 Lunes
1 1 2236 Martes
2 2 2310 Miércoles
3 3 2586 Jueves
4 4 2959 Viernes
5 5 3322 Sábado
6 6 3455 Domingo

Vemos que hacia el fin de semana la demanda de taxis aumenta.

Ahora grafico la cantidad de viajes por día. Primero usando Altair.

In [0]:
alt.Chart(source2).mark_line(clip=True).encode(
    x=alt.X('dia_de_la_semana_nombre', 
            title='Dia de la semana',
            sort=alt.EncodingSortField(field="dia_de_la_semana", order='ascending'),
            axis=alt.Axis(labelAngle=0)),
    y=alt.Y('count', title='Cantidad de viajes', scale=alt.Scale(domain=(2000, 3500)))
).properties(width=400)
Out[0]:

Ahora usando Pandas.

In [0]:
chart = source2.plot.line(x='dia_de_la_semana_nombre',y='count',rot=0, legend=False)
chart.set_xlabel('Día de la semana')
chart.set_ylabel('Número de viajes')
chart.set_xticklabels(chart.get_xticklabels(), rotation=0);

Ahora veamos a qué horas se hacen viajes más largos.

Primero agrego la columna hora al DataFrame, teniendo en cuenta la hora de partida.

In [0]:
df['hora'] = pd.DatetimeIndex(df['fecha_inicio']).hour
df[['fecha_inicio','hora']].head(100)
Out[0]:
fecha_inicio hora
0 2017-05-01 00:12:48.000 0
1 2017-05-01 00:17:21.000 0
2 2017-05-01 00:16:03.000 0
3 2017-05-01 00:34:39.000 0
4 2017-05-01 00:32:02.000 0
... ... ...
95 2017-05-02 12:00:29.000 12
96 2017-05-02 12:01:25.000 12
97 2017-05-02 12:38:45.000 12
98 2017-05-02 13:28:53.000 13
99 2017-05-02 14:22:31.000 14

100 rows × 2 columns

También agrego una columna donde calculo la duración de los viajes en minutos en vez de segundos.

In [0]:
df['duracion_en_minutos'] = df['duracion'].div(60)
df[['duracion','duracion_en_minutos']].head()
Out[0]:
duracion duracion_en_minutos
0 1101 18.350000
1 675 11.250000
2 1230 20.500000
3 1218 20.300000
4 995 16.583333

Ahora agrupo por hora y saco la duración promedio de los viajes para cada hora.

In [0]:
source3 = df.groupby(['hora'])['duracion_en_minutos'].mean().reset_index(name='duracion_promedio')
source3
Out[0]:
hora duracion_promedio
0 0 15.140292
1 1 15.045816
2 2 15.824646
3 3 15.967629
4 4 16.599312
5 5 17.252701
6 6 15.857130
7 7 14.686588
8 8 15.195546
9 9 15.921116
10 10 15.213060
11 11 15.927577
12 12 15.819900
13 13 16.263444
14 14 15.933805
15 15 15.362177
16 16 15.536262
17 17 15.585085
18 18 15.451519
19 19 15.451787
20 20 15.581126
21 21 14.839449
22 22 14.557418
23 23 14.557177

Vemos que la duración promedio de los viajes es similar a toda hora, con un máximo a las 5am y un mínimo a las 11pm.

Grafico la duración promedio de viaje para cada hora. La linea roja representa la duración promedio de viaje a toda hora.

In [0]:
grafico = alt.Chart(source3).mark_line(clip=True).encode(
    x=alt.X('hora', 
            title='Hora',
            axis=alt.Axis(labelAngle=0),
            scale=alt.Scale(domain=(0, 23))),
    y=alt.Y('duracion_promedio', 
            title='Duración promedio de viaje en minutos',
            scale=alt.Scale(domain=(14, 18)))
).properties(width=400)

rule = alt.Chart(source3).mark_rule(color='red').encode(
    y='mean(duracion_promedio):Q'
)

grafico + rule
Out[0]:
In [0]:
prom = source3['duracion_promedio'].mean()
print('Duración promedio de viaje:', round(prom, 2), 'minutos')
Duración promedio de viaje: 15.57 minutos

Vemos que la duración promedio de viaje es de 15.57 minutos

Ahora analizo si hay taxistas que suelen hacer viajes más largos que otros.

Primero agrupo por id de taxista y calculo la duración promedio de sus viajes.

In [0]:
source4 = df.groupby(['id_taxista_r'])['duracion_en_minutos'].mean().reset_index(name='duracion_promedio')
source4
Out[0]:
id_taxista_r duracion_promedio
0 1 17.544444
1 2 16.123744
2 3 18.829630
3 4 16.593333
4 5 15.207576
... ... ...
1210 1211 15.416667
1211 1212 19.833333
1212 1213 11.100000
1213 1214 21.138889
1214 1215 31.733333

1215 rows × 2 columns

Graficamos la información para ver si hay taxistas con promedio de viaje notoriamente mayor.

In [0]:
alt.Chart(source4).mark_bar(clip=True).encode(
    x=alt.X('id_taxista_r', 
            title='ID del taxista',
            axis=alt.Axis(labelAngle=0),
            scale=alt.Scale(domain=(0, 1250))),
    y=alt.Y('duracion_promedio', 
            title='Duración promedio de viaje en minutos')
).properties(width=1000).mark_bar(size=1.5)
Out[0]:

Vemos que hay algunos taxistas que se destacan por hacer viajes largos.

Obtengo los 10 taxistas con promedio de viaje más largo.

In [0]:
source4.nlargest(10,'duracion_promedio')
Out[0]:
id_taxista_r duracion_promedio
160 161 33.250000
347 348 33.016667
291 292 32.766667
1214 1215 31.733333
1108 1109 31.683333
300 301 31.600000
915 916 29.416667
150 151 29.141667
995 996 28.766667
537 538 28.616667

Vemos que 6 taxistas tienen un promedio de viaje de más de media hora.

Ahora veamos los 10 promedios de viaje más cortos.

In [0]:
source4.nsmallest(10,'duracion_promedio')
Out[0]:
id_taxista_r duracion_promedio
1085 1086 2.366667
73 74 2.483333
1098 1099 2.488889
710 711 2.550000
205 206 3.000000
1072 1073 3.733333
859 860 3.900000
1096 1097 3.983333
309 310 4.083333
597 598 4.350000

Vemos que hay 8 taxistas que suelen hacer viajes de menos de 4 minutos.

Ahora analicemos la cantidad de pasajeros en los viajes. En primer lugar veamos las frecuencias para el número de pasajeros.

In [0]:
alt.data_transformers.disable_max_rows()

alt.Chart(df).mark_bar().encode(
    alt.X("cantidad_pasajeros:Q", 
          title='Cantidad de pasajeros', 
          axis=alt.Axis(labelAngle=0),
          bin=alt.Bin(extent=[1, 5], step=1)),
    alt.Y('count()', title='Cantidad de viajes'),
).properties(width=200).mark_bar(size=49)
Out[0]:

Vemos que más de la mitad de los viajes son de 1 pasajero, seguidos por los de 2, luego los de 3, y por último los de 4.

Ahora veamos si los viajes de más pasajeros suelen ser más largos o no. Primero agrego la columna distancia al DataFrame.

In [0]:
from geopy.point import Point
from geopy.distance import geodesic

df['distancia'] = df.apply(lambda dato: int(geodesic( 
    Point(latitude=dato['origen_viaje_y'], longitude=dato['origen_viaje_x']) , 
    Point(latitude=dato['destino_viaje_y'], longitude=dato['destino_viaje_x'])).meters), 
    axis=1).div(1000)
df[['distancia']].head(100)
Out[0]:
distancia
0 4.427
1 2.306
2 6.229
3 4.514
4 3.512
... ...
95 4.829
96 1.265
97 6.359
98 2.503
99 3.013

100 rows × 1 columns

Ahora calculo la distancia promedio para las distintas cantidades de pasajeros.

In [0]:
source5 = df.groupby(['cantidad_pasajeros'])['distancia'].mean().reset_index(name='distancia_promedio')
source5
Out[0]:
cantidad_pasajeros distancia_promedio
0 1 4.023244
1 2 3.755107
2 3 3.703815
3 4 3.929891

Vemos que, al parecer, un mayor número de pasajeros no significa viajes más largos (con el objetivo de ahorrar dinero).

Graficamos los resultados obtenidos.

In [0]:
alt.Chart(source5).mark_bar().encode(
    x=alt.X('cantidad_pasajeros:O', title='Cantidad de pasajeros', axis=alt.Axis(labelAngle=0)),
    y=alt.Y('distancia_promedio', title='Distancia promedio del viaje en km')
).properties(width=300).mark_bar(size=30)
Out[0]:

Por último, analicemos si un mayor tiempo de viaje significa una mayor distancia recorrida.

Primero extraigo los datos que me interesan del DataFrame.

In [0]:
source6 = df[['duracion_en_minutos','distancia']]
source6
Out[0]:
duracion_en_minutos distancia
0 18.350000 4.427
1 11.250000 2.306
2 20.500000 6.229
3 20.300000 4.514
4 16.583333 3.512
... ... ...
19143 12.383333 3.202
19144 8.150000 2.025
19145 15.816667 2.797
19146 10.600000 1.512
19147 27.433333 8.245

19148 rows × 2 columns

Luego grafico en un scatter plot. Calculo la regresión lineal.

In [0]:
scatterplot = alt.Chart(source6).mark_point(size=30).encode(
    x=alt.X('duracion_en_minutos:Q', title='Duración del viaje en minutos', axis=alt.Axis(labelAngle=0)),
    y=alt.Y('distancia', title='Distancia del viaje en km',scale=alt.Scale(domain=(0, 40)))
  ).properties(width=500)

regression = scatterplot.transform_regression('duracion_en_minutos', 'distancia',method="linear"
).mark_line(color="red")

scatterplot + regression
Out[0]:

Vemos que en lineas generales, a mayor duración del viaje, mayor es la distancia que se recorre. De todos modos, esto no siempre es así y vemos valores outliers que muestran que para viajes largos se recorrió muy poca o demasiada distancia. El primer caso puede deberse a factores como el tráfico, que hacen que un viaje de corta distancia tarde más en realizarse. El segundo puede deberse a la utilización de medios como autopistas, que permiten recorrer más distancia en menor tiempo dado que la velocidad máxima permitida es mayo.